//
//  WebSocket.h
//  Socket.IO-Client
//
//  Created by alanwang.dev on 16/8/8.
//  Copyright © 2016年 com.alanwang.dev. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef NS_ENUM(UInt8, OpCode) {
  ContinueFrame = 0x0,         // slow at beginning and end
  TextFrame = 0x1,            // slow at beginning
  BinaryFrame = 0x2,           // slow at end
  ConnectionClose = 0x8,
  Ping = 0x9,
  Pong = 0xA
};

typedef NS_ENUM(UInt16, CloseCode) {
  Normal                 = 1000,
  GoingAway              = 1001,
  ProtocolError          = 1002,
  ProtocolUnhandledType  = 1003,
  // 1004 reserved.
  NoStatusReceived       = 1005,
  //1006 reserved.
  Encoding               = 1007,
  PolicyViolated         = 1008,
  MessageTooBig          = 1009
};

typedef NS_ENUM(NSInteger, InternalErrorCode) {
  OutputStreamWriteError = 1
};

typedef void(^CompletionBlock) ();

@class  WebSocket;
@class  SSLSecurity;

@protocol WebSocketDelegate

- (void)websocketDidConnect:(WebSocket *)socket;
- (void)websocketDidDisconnect:(WebSocket *)socket error:(NSError *)error;
- (void)websocketDidReceiveMessage:(WebSocket *)socket text:(NSString *)text;
- (void)websocketDidReceiveData:(WebSocket *)socket data:(NSData *)data;

@end

@protocol WebSocketPongDelegate
- (void)websocketDidReceivePong:(WebSocket *)socket;
@end


@interface WebSocket : NSObject<NSStreamDelegate>
@property (nonatomic,strong) dispatch_queue_t queue;

@property (nonatomic, weak) id<WebSocketDelegate> deleate;
@property (nonatomic, weak) id<WebSocketPongDelegate> pongDelegate;
@property (nonatomic, copy) void(^onConnect)(void);
@property (nonatomic, copy) void(^onDisconnect)(NSError *);
@property (nonatomic, copy) void(^onText)(NSString *);
@property (nonatomic, copy) void(^onData)(NSData *);
@property (nonatomic, copy) void(^onPong)(void);
@property (nonatomic, strong) NSMutableDictionary *headers;
@property (nonatomic, assign) BOOL voipEnabled;
@property (nonatomic, assign) BOOL selfSignedSSL;
@property (nonatomic, strong) SSLSecurity *security;
@property (nonatomic, copy) NSArray *enabledSSLCipherSuites;
@property (nonatomic, copy) NSString *origin;
@property (nonatomic, assign) NSInteger timeout;
@property (nonatomic, assign) BOOL isConnected;

- (instancetype) initWithURL:(NSURL *)url protocols:(NSArray *)protocols;

/**
 *  @brief 写入文字
 *
 *  @param str
 *  @param completion 成功回调
 */
- (void) wirteString:(NSString *)str completion:(CompletionBlock)completion;

/**
 *  @brief 写入data
 *
 *  @param data       <#data description#>
 *  @param completion 成功回调
 */
- (void) writeData:(NSData *)data completion:(CompletionBlock)completion;

/**
 *  @brief 写入ping
 *
 *  @param data       <#data description#>
 *  @param completion 成功回调
 */
- (void) writePing:(NSData *)data completion:(CompletionBlock)completion;
/**
 *  @brief delegate for the stream methods. Processes incoming bytes
 *
 *  @param astream   <#astream description#>
 *  @param eventCode <#eventCode description#>
 */
- (void) stream:(NSStream *)astream handleEvent:(NSStreamEvent)eventCode;


/**
 *  @brief 后台连接webscoket
 */
- (void) connect;

/**
 *  @brief 断开连接
 *
 *  @param forceTimeout 超时时间
 */
- (void) disconnect:(NSTimeInterval)forceTimeout;
@end

@interface WSResponse : NSObject
@property (nonatomic, assign) BOOL isFin;
@property (nonatomic, assign) OpCode code;
@property (nonatomic, assign) NSInteger bytesLeft;
@property (nonatomic, assign) NSInteger frameCount;
@property (nonatomic, strong) NSMutableData *buffer;
@end

@interface SSLCert : NSObject

@property (nonatomic) SecKeyRef key;
@property (nonatomic) NSData *data;

- (id) initWithData:(NSData *)data;

- (id) initWithKey:(SecKeyRef)key;
@end


@interface SSLSecurity : NSObject

@property (nonatomic, assign) BOOL validateDN;
@property (nonatomic, assign) BOOL isRead;
@property (nonatomic, strong) NSMutableArray *certificates;
@property (nonatomic, strong) NSMutableArray *pubkeys;
@property (nonatomic, assign) BOOL usePublicKeys;
- (BOOL) isValid:(SecTrustRef )trust domain:(NSString *)domain;
@end
